package client

import (
	"chess_platform/internal/alisdk"
	. "chess_platform/internal/common"
	"chess_platform/internal/token"
	"chess_platform/models/client"
	"chess_platform/models/h5"
	"encoding/json"
	"fmt"
	"time"
)

//client用户
type UserController struct {
	GrantController
}

func (b *UserController) URLMapping() {
	b.Mapping("NewIdentity", b.NewIdentity)
	b.Mapping("UpdateLocation", b.UpdateLocation)
	b.Mapping("UpdateCityCode", b.UpdateCityCode)

	b.Mapping("BindPhone", b.BindPhone)
	b.Mapping("UnbindPhone", b.UnbindPhone)
	b.Mapping("GetUserInfo", b.GetUserInfo)
	b.Mapping("MultiUserInfo", b.MultiUserInfo)
	b.Mapping("Logout", b.Logout)
	b.Mapping("RefreshToken", b.RefreshToken)
}

// @Title 新增实名认证
// @Description 新增实名认证
// @Param   identity  	     body    string  true      "身份证号码"
// @Param   real_name        body    string  true      "真实姓名"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /new-identity [post]
func (b *UserController) NewIdentity() {
	type Params struct {
		Identity string `json:"identity"`
		RealName string `json:"real_name"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	b.Valid.Length(p.Identity, 18, "identity").Message("身份证号码长度为18位")
	b.Valid.Identity(p.Identity, "identity").Message("请收入正确的身份证,X为大写字母")
	b.Valid.MatchChinese(p.RealName, "real_name").Message("请输入中文")
	b.Valid.MinSize(p.RealName, 2, "real_name").Message("名字长度2-16")
	b.Valid.MaxSize(p.RealName, 16, "real_name").Message("名字长度2-16")
	if !b.VerifyParamsError() {
		return
	}

	data := map[string]interface{}{
		"identity":  p.Identity,
		"real_name": p.RealName,
	}
	//身份认证，纯粹做一下样子
	client.UpdateUser(data, b.Uid)
	key := fmt.Sprintf("%v%v", KeyClientUserInfo, b.Uid)
	DelCache(RedisCache, key)
	b.ResponseSuccess()

}

// @Title 刷新用户city code
// @Description 刷新用户city code
// @Param   city_code   body    string  true      "city_code"
// @Success 0
// @Failure 400
// @Failure 404
// @router /update-city-code [post]
func (b *UserController) UpdateCityCode() {
	type Params struct {
		CityCode string `json:"city_code"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	u := map[string]interface{}{
		"city_code": p.CityCode,
		"city_name": CityCode[p.CityCode],
	}
	_, err := client.UpdateUser(u, b.Uid)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	key := fmt.Sprintf("%v%v", KeyClientUserInfo, b.Uid)
	DelCache(RedisCache, key)
	b.ResponseSuccess()

}

// @Title 刷新用户坐标
// @Description 刷新用户坐标
// @Param   lon  		body    string  true      "经度"
// @Param   lat  		body    string  true      "纬度"
// @Param   city_name   body    string  true      "城市名字"
// @Param   county_name body    string  true      "区或县的名字"
// @Success 0
// @Failure 400
// @Failure 404
// @router /update-location [post]
func (b *UserController) UpdateLocation() {
	type Params struct {
		Lon        string `json:"lon"`
		Lat        string `json:"lat"`
		CityName   string `json:"city_name"`
		CountyName string `json:"county_name"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	var allCode CountyCityProvince
	countyCode, ok := CityName[p.CountyName]
	if ok {
		allCode = countyCode
	} else {
		cityCode, ok := CityName[p.CityName]
		if ok {
			allCode = cityCode
		}
	}
	u := map[string]interface{}{
		"lon": p.Lon,
		"lat": p.Lat,
	}
	_, err := client.UpdateUser(u, b.Uid)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	key := fmt.Sprintf("%v%v", KeyClientUserInfo, b.Uid)
	DelCache(RedisCache, key)
	b.Res.Data = allCode
	b.ResponseSuccess()

}

// @Title 手机号绑定
// @Description 手机号绑定
// @Param   phone   body    string  true      "手机号"
// @Param   captcha body    string  true      "验证码"
// @Success 0
// @Failure 400
// @Failure 404
// @router /bind-phone [post]
func (b *UserController) BindPhone() {
	type Params struct {
		Phone   string `json:"phone"`
		Captcha string `json:"captcha"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	b.Valid.Required(p.Phone, "phone").Message("手机号不能为空")
	b.Valid.Phone(p.Phone, "phone").Message("错误的手机号")
	b.Valid.Required(p.Captcha, "captcha").Message("验证码不能为空")
	b.Valid.Numeric(p.Captcha, "captcha").Message("验证码为6位数字")
	b.Valid.Length(p.Captcha, 6, "captcha").Message("验证码为6位数字")
	if !b.VerifyParamsError() {
		return
	}
	err, ok := alisdk.VerifySMSCaptcha(p.Phone, p.Captcha, KeyClientPhone, MemCache)
	if !ok {
		b.Res.Code = ErrCaptchaVerify
		b.Res.Msg = err.Error()
		b.Response()
		LogClient.Notice(err.Error())
		return
	}
	uid, phoneTime, err := client.IsUserExistByPhone(p.Phone)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	if uid == b.Uid {
		b.ResponseSuccess("已经绑定,无需重复绑定")
		return
	}

	if uid != 0 {
		b.Res.Code = ErrUserAlreadyExist
		b.Res.Msg = MsgErrPhoneAlreadyBind
		b.Response()
		return
	}

	_, err = client.UpdateUserPhone(p.Phone, b.Uid)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}

	key := fmt.Sprintf("%v%v", KeyClientUserInfo, b.Uid)
	DelCache(RedisCache, key)
	b.Res.Data = map[string]interface{}{
		"phone": HidePhoneNumber(p.Phone),
	}
	b.ResponseSuccess()

	//首次绑定手机才赠送钻石
	if phoneTime == 0 { //首次绑定
		rule, err := h5.RuleByType(RulePlayerBindPhone)
		if err == nil && rule.Amount != 0 { //有绑定手机赠送钻石的活动
			pl, ok := client.IsPhoneBindEver(p.Phone)
			if ok { //曾经绑定过,不赠送钻石,防止刷钻石
				//发送邮件通知玩家,此手机号已经被某某绑定过了，不能赠送
				t := time.Unix(pl.CreateTime, 0)
				content := fmt.Sprintf("此手机号(%v)曾经被玩家(ID:%v)在%v绑定,所以不能再赠送钻石",
					p.Phone, pl.Uid, t.Format("2006-01-02 15:04"))
				data := map[string]interface{}{
					"type":      EmailTypeSys,
					"suid":      0,
					"ruid":      b.Uid,
					"nickname":  "系统消息",
					"title":     "首次绑定手机赠送钻石失败",
					"content":   content,
					"status":    0,
					"send_time": time.Now().Unix(),
				}
				client.SendEmailAndNotifyClient(data, b.Uid, 0, "")

			} else { //此手机从来没被绑定
				//发送邮件通知玩家通过邮件领取钻石
				data := map[string]interface{}{
					"type":         EmailTypeSys,
					"suid":         0,
					"ruid":         b.Uid,
					"nickname":     "系统消息",
					"title":        "首次绑定手机赠送钻石",
					"content":      "感谢您绑定手机,请领取奖励",
					"status":       0,
					"attachment":   fmt.Sprintf(`[{"qty":%v,"type":1}]`, rule.Amount),
					"send_time":    time.Now().Unix(),
					"operate_type": SysOpBindPhone,
				}
				client.SendEmailAndNotifyClient(data, b.Uid, 0, "")
			}
		}

	}
	//绑定成功，需要写手机号日志
	data := map[string]interface{}{
		"uid":         b.Uid,
		"phone":       p.Phone,
		"create_time": time.Now().Unix(),
	}
	client.NewPhoneLog(data)

}

// @Title 解绑手机号
// @Description 解绑手机号
// @Param   old_phone body    string  true      "旧手机号"
// @Param   captcha   body    string  true      "验证码"
// @Success 0 {string} 状态码
// @Failure 399
// @router /unbind-phone [post]
func (b *UserController) UnbindPhone() {
	type Params struct {
		OldPhone string `json:"old_phone"`
		Captcha  string `json:"captcha"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}

	b.Valid.Phone(p.OldPhone, "old_phone").Message("请输入正确的原手机号")
	b.Valid.Required(p.Captcha, "captcha").Message("验证码不能为空")
	b.Valid.Numeric(p.Captcha, "captcha").Message("验证码为6位数字")
	b.Valid.Length(p.Captcha, 6, "captcha").Message("验证码为6位数字")
	if !b.VerifyParamsError() {
		return
	}

	err, ok := alisdk.VerifySMSCaptcha(p.OldPhone, p.Captcha, KeyClientPhone, MemCache)
	if !ok {
		b.Res.Code = ErrCaptchaVerify
		b.Res.Msg = err.Error()
		b.Response()
		return
	}

	//如果没有输入正确的手机号，上面验证码校验不通过,不会走到这一步
	uid, phoneTime, err := client.IsUserExistByPhone(p.OldPhone)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	if uid != b.Uid {
		b.ResponseFail("请输入正确的原手机号")
		return
	}
	if time.Now().Unix()-phoneTime < 172800 { //48小时之后才能解绑
		b.ResponseFail("48小时内不能解绑手机号")
		return
	}

	//解绑手机号，所以把手机号置为空传过去就行了
	_, err = client.UpdateUserPhone("", b.Uid)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	key := fmt.Sprintf("%v%v", KeyClientUserInfo, b.Uid)
	DelCache(RedisCache, key)
	b.ResponseSuccess()

}

// @Title 获取用户信息
// @Description 获取用户信息
// @Param   quid     body      true      "查询用户ID"
// @Success 0
// @Failure 400
// @Failure 404
// @router /getuserinfo [post]
func (b *UserController) GetUserInfo() {
	type Params struct {
		Quid int64
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}

	data, err := client.QueryUserInfoById(p.Quid)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	data.Phone = HidePhoneNumber(data.Phone)
	b.Res.Data = data
	b.ResponseSuccess()
}

// @Title 获取多个玩家用户信息
// @Description 获取多个玩家用户信息
// @Param   uid     body  int    true      "查询玩家用户ID,传递形式 uid:[1,2,3,4,5]"
// @Success 0
// @Failure 400
// @Failure 404
// @router /multi-user-info [post]
func (b *UserController) MultiUserInfo() {
	type Params struct {
		Uid string `json:"uid"`
	}
	var p Params
	var u []int64
	if !b.DecodeParams(&p) {
		return
	}
	err := json.Unmarshal([]byte(p.Uid), &u)
	if err != nil {
		LogClient.Error(b.SystemError(err.Error()))
		return

	}
	data, err := client.MultiUserInfoById(u)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = data
	b.ResponseSuccess()
}

// @Title 登出
// @Description 登出
// @Success 0 {string} token
// @Failure 400
// @Failure 404
// @router /logout [post]
func (b *UserController) Logout() {
	//key := fmt.Sprintf("%v%v", KeyClientTokenCache, b.Uid)
	//RedisCache.Delete(key)
	b.ResponseSuccess()
}

// @Title 刷新token(定时刷新,每隔30分钟)
// @Description 刷新token(定时刷新,每隔30分钟)
// @Success 0 {string} 状态
// @router /refresh-token [post]
func (b *UserController) RefreshToken() {
	//info = 0表示今天不是第一次登录，刷新token当然不是第一次登录了
	tokenStr := token.Create(b.Uid, 0, TokenClient, 0)
	/*
		key := fmt.Sprintf("%v%v", KeyClientTokenCache, b.Uid)
		RedisCache.Put(key, tokenStr, time.Duration(Secret.ClientTokenCacheExpire)*time.Second)
	*/
	b.Res.Token = tokenStr
	b.ResponseSuccess()
}
